﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using System.Collections;
using ProgNetUtils;
using System.Drawing;
using System.Reflection;
using DevExpress.XtraBars;

namespace ProgNetExtensions.Security
{
    [ProvideProperty("SecurityId", typeof(object))]
    public class SecurityInfoProvider : Component, IExtenderProvider, ISupportInitialize
    {
        private bool isInitialized = false;
        private Hashtable nameObjects = new Hashtable();

        public SecurityInfoProvider()
        {
            SecurityInfo.SecurityChanged += new EventHandler(SecurityInfo_SecurityChanged);
        }

        void SecurityInfo_SecurityChanged(object sender, EventArgs e)
        {
            foreach (object obj in nameObjects.Keys)
            {
                if (CanExtend(obj))
                {
                    SecurityHelper helper = nameObjects[obj] as SecurityHelper;
                    if (helper != null)
                    {
                        SetPropertyValue(obj);
                        helper.WasChanged = false;
                    }
                }
            }
        }

        #region SecurityId
        [Category("ProgNet SecurityInfo")]
        [DisplayName("SecurityId")]
        public string GetSecurityId(object sender)
        {
            string result = string.Empty;
            SecurityHelper helper = null;
            if (PnInitialization.IsAppRunning && isInitialized)
            {
                string name = sender.GetObjectName();
                if (name.IsNotEmpty())
                {
                    helper = GetHelperByName(name);
                }
            }
            else
            {
                if (nameObjects.ContainsKey(sender))
                {
                    helper = nameObjects[sender] as SecurityHelper;
                }
            }
            if (helper != null)
                result = helper.SecurityId;

            return result;
        }

        public void SetSecurityId(object sender, string value)
        {
            SecurityHelper helper = null;

            if (nameObjects.ContainsKey(sender))
            {
                helper = nameObjects[sender] as SecurityHelper;
            }
            else
            {
                helper = new SecurityHelper();
                nameObjects.Add(sender, helper);
            }

            if (helper != null)
                helper.SecurityId = value;

            SetPropertyValue(sender);
        }
        #endregion
        private SecurityHelper GetHelperByName(string name)
        {
            foreach (object obj in nameObjects.Keys)
            {
                if (name == obj.GetObjectName())
                    return nameObjects[obj] as SecurityHelper;
            }
            return null;
        }

        protected virtual void SetPropertyValue(object sender)
        {
            string SecurityId = GetSecurityId(sender);
            SecurityInfo info = SecurityInfo.GetSecurityInfo(SecurityId);
            if (info != null)
            {
                if (info.Name == "s222")
                {

                }
                if (sender is BarSubItem)
                {
                    if ((sender as BarSubItem).Links == null || (sender as BarSubItem).Links.Count == 0)
                        sender.SetProperty(GetEnableProperty(sender), (info.Enabled ? GetTrueEnabledValue(sender) : GetFalseEnabledValue(sender)));
                    else
                    {
                        if (!info.Enabled)
                        {
                            LockChildren((sender as BarSubItem));
                        }
                    }
                }
                else
                {
                    sender.SetProperty(GetEnableProperty(sender), (info.Enabled ? GetTrueEnabledValue(sender) : GetFalseEnabledValue(sender)));
                }
                sender.SetProperty(GetVisibleProperty(sender), (info.Visible ? GetTrueVisibleValue(sender) : GetFalseVisibleValue(sender)));
                if (PnInitialization.IsAppRunning)
                {
                    SetPaintEvent(sender);
                }
            }
        }

        private void LockChildren(BarSubItem barSubItem)
        {
            foreach (BarItemLink link in barSubItem.ItemLinks)
            {
                SetPropertyValue(link.Item);
            }
        }
        protected virtual void SetPaintEvent(object sender)
        {
            Type t = sender.GetType();
            EventInfo paintEvent = t.GetEvent("Paint");
            if (paintEvent != null)
            {
                paintEvent.RemoveEventHandler(sender, Delegate.CreateDelegate(paintEvent.EventHandlerType, this, "LockProvider_Paint"));
                paintEvent.AddEventHandler(sender, Delegate.CreateDelegate(paintEvent.EventHandlerType, this, "LockProvider_Paint"));
            }
            else
            {
                if (sender is BarItem)
                {
                    string SecurityId = GetSecurityId(sender);
                    SecurityInfo info = SecurityInfo.GetSecurityInfo(SecurityId);
                    if (info != null)
                    {
                        SetGlyphDisabled((sender as BarItem), info.Enabled);
                    }
                }
            }
        }
        protected virtual string GetEnableProperty(object sender)
        {
            if (sender.HasProperty("Enabled"))
                return "Enabled";
            else
                return null;
        }
        protected virtual string GetVisibleProperty(object sender)
        {
            if (sender is BarItem)
                return "Visibility";
            if (sender.HasProperty("Visible"))
                return "Visible";
            else
                return null;
        }
        protected virtual object GetTrueEnabledValue(object sender)
        {
            return true;
        }
        protected virtual object GetFalseEnabledValue(object sender)
        {
            return false;
        }
        protected virtual object GetTrueVisibleValue(object sender)
        {
            if (sender is BarItem)
                return BarItemVisibility.Always;
            return true;
        }
        protected virtual object GetFalseVisibleValue(object sender)
        {
            if (sender is BarItem)
                return BarItemVisibility.Never;
            return false;
        }
        #region paint
        private void SetGlyphDisabled(BarItem item,bool enabled)
        {
            if (enabled)
            {
                if (item.ImageIndex >= 0)
                    item.Glyph = ((System.Windows.Forms.ImageList)item.Manager.Images).Images[item.ImageIndex];
                else
                    item.Glyph = null;
            }
            else
            {
                if (item.ImageIndex >= 0)
                    item.Glyph = MakeIconDisabled(((System.Windows.Forms.ImageList)item.Manager.Images).Images[item.ImageIndex]);
                else
                {
                    SetNullImage(item);
                    item.Glyph = MakeIconDisabled(null);
                }
            }
        }

        private void SetNullImage(DevExpress.XtraBars.BarItem item)
        {
            Bitmap bmp = new Bitmap(16, 16);
            bmp.MakeTransparent(bmp.GetPixel(0, 0));
            item.PaintStyle = DevExpress.XtraBars.BarItemPaintStyle.CaptionGlyph;
            item.Glyph = bmp;
        }

        private Bitmap MakeIconDisabled(Image image)
        {
            Bitmap bmpRet = null;
            int imageWidth = 16;
            int imageHeight = 16;

            Bitmap bmpDisabled = new Bitmap(imageWidth, imageHeight);
            Graphics graphicsDisabled = Graphics.FromImage(bmpDisabled);
            if (image != null)
            {
                int x, y;
                x = y = 0;
                Rectangle srcRect = new Rectangle(0, 0, imageWidth, imageHeight);
                graphicsDisabled.DrawImage(image, new Point[] { new Point(x, y), new Point(x + srcRect.Width, y), new Point(x, y + srcRect.Height) }, srcRect, GraphicsUnit.Pixel, DevExpress.XtraBars.Painters.PaintHelper.DisabledAttributes);
            }
            DrawLockImage(graphicsDisabled);
            bmpRet = (Bitmap)bmpDisabled.Clone();

            return bmpRet;
        }

        void LockProvider_Paint(object sender, PaintEventArgs e)
        {
            string SecurityId = GetSecurityId(sender);
            SecurityInfo info = SecurityInfo.GetSecurityInfo(SecurityId);
            if (info != null && !info.Enabled)
            {
                DrawLockImage(e.Graphics);
            }
        }
        protected void DrawLockImage(Graphics g)
        {
            Image img = SecurityInfo.LockImage;
            if (img == null)
                img = Properties.Resources.lock32;
            g.DrawImage(img, new Rectangle(3, 3, 12, 12));
        }
        #endregion
        #region IExtenderProvider Members

        public virtual bool CanExtend(object extendee)
        {
            if (extendee is Button ||
                extendee is SimpleButton ||
                extendee is BarItem)
            {
                return true;
            }
            return false;
        }

        #endregion

        #region ISupportInitialize Members

        public void BeginInit()
        {
            isInitialized = false;
        }

        public void EndInit()
        {
            isInitialized = true;
            foreach (object obj in nameObjects.Keys)
            {
                if (CanExtend(obj))
                {
                    SecurityHelper helper = nameObjects[obj] as SecurityHelper;
                    if (helper != null)
                    {
                        if (helper.WasChanged)
                        {
                            SetPropertyValue(obj);
                            helper.WasChanged = false;
                        }
                    }
                }
            }
        }

        #endregion
    }

    public class SecurityHelper
    {
        private string _SecurityId;
        private bool _WasChanged = true;

        public string SecurityId
        {
            get { return _SecurityId; }
            set
            {
                _SecurityId = value;
                WasChanged = true;
            }
        }
        public bool WasChanged
        {
            get { return _WasChanged; }
            set { _WasChanged = value; }
        }

    }
}
